package com.excel.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * Excel模板生成工具类
 */
public class ExcelTemplateUtil {

    private static final Logger log = LoggerFactory.getLogger(ExcelTemplateUtil.class);

    /**
     * Sheet配置类
     */
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class SheetConfig<T> {
        /**
         * Sheet名称
         */
        private String sheetName;

        /**
         * 表头对应的类（可选，为null时不生成表头）
         */
        private Class<T> headerClass;

        /**
         * 伪数据列表（可选）
         */
        private List<T> mockData;

        /**
         * Sheet索引（可选，默认按添加顺序）
         */
        private Integer sheetIndex;
    }

    /**
     * 生成Excel模板并输出到响应流
     *
     * @param response     HTTP响应
     * @param fileName     文件名（不含扩展名）
     * @param sheetConfigs Sheet配置列表
     */
    public static void generateTemplate(HttpServletResponse response, String fileName, List<SheetConfig<?>> sheetConfigs) {
        try {
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");

            generateTemplate(response.getOutputStream(), sheetConfigs);
        } catch (IOException e) {
            log.error("生成Excel模板失败", e);
//            throw new BusinessException(ErrorCode.GENERATE_EXCEL_TEMPLATE_FAILED);
        }
    }

    /**
     * 生成Excel模板并输出到指定流
     *
     * @param outputStream 输出流
     * @param sheetConfigs Sheet配置列表
     */
    public static void generateTemplate(OutputStream outputStream, List<SheetConfig<?>> sheetConfigs) {
        if (CollectionUtils.isEmpty(sheetConfigs)) {
//            throw new CommonException("Sheet配置不能为空");
            return;
        }

        try {
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
            // 按顺序处理每个Sheet
            String sheetNamePrefix = "sheet";
            for (int i = 0; i < sheetConfigs.size(); i++) {
                SheetConfig<?> config = sheetConfigs.get(i);
                int sheetIndex = config.getSheetIndex() != null ? config.getSheetIndex() : i;
                String sheetName = StrUtil.isBlank(config.sheetName) ? sheetNamePrefix + (i + 1) : config.sheetName;
                WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex, sheetName).head(config.headerClass)
                        .registerWriteHandler(createNoStyleStrategy())
                        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                        .build();
                excelWriter.write(config.mockData, writeSheet);
            }
            excelWriter.finish();
        } catch (Exception e) {
            log.error("生成Excel模板失败", e);
//            throw new IllegalStateException(ErrorCode.GENERATE_EXCEL_TEMPLATE_FAILED);
        }
    }


    /**
     * 创建无风格策略
     *
     * @return {@link HorizontalCellStyleStrategy }
     */
    private static HorizontalCellStyleStrategy createNoStyleStrategy() {
        // 表头样式 - 无任何特殊样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setBold(false); // 不加粗
        headWriteCellStyle.setWriteFont(headWriteFont);
        headWriteCellStyle.setFillForegroundColor(null); // 无背景色
        headWriteCellStyle.setFillPatternType(FillPatternType.NO_FILL); // 无填充

        // 内容样式 - 无任何特殊样式
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setBold(false);
        contentWriteCellStyle.setWriteFont(contentWriteFont);

        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }

    /**
     * 创建带指定索引的Sheet配置
     */
    public static <T> SheetConfig<T> createSheet(String sheetName, Class<T> headerClass, List<T> mockData, int sheetIndex) {
        return SheetConfig.<T>builder()
                .sheetName(sheetName)
                .headerClass(headerClass)
                .mockData(mockData)
                .sheetIndex(sheetIndex)
                .build();
    }
}